/*
 * vim: ts=4 sw=4 fdm=marker noet tw=78 ai
 * %%LICENSE%%
 */
#include <sys/cdefs.h>
#ifdef __FBSDID
__FBSDID("$Coar$");
#endif

#include <sys/queue.h> // SLIST
#include <stdlib.h> // malloc

#include <err.h>
#include <assert.h>

#include <ldap.h>
#include <ldap_schema.h>

#include "extern.h"
#include "search.h"
#include "attrdfn.h"

static attr_dfn_entry_t *attr_dfn_new(LDAPAttributeType *);

int
lde_add_attr_dfn(runtime_t *ctx, char *schema)
{
	LDAPAttributeType *ad;
	const char *errpos;
	attr_dfn_entry_t *new, *tmp;
	int retval = LDAP_SUCCESS;

	assert(ctx != NULL);
	assert(ctx->ld != NULL);
	assert(schema != NULL);
	assert(schema[0] != '\0'); // empty schema
	TRACEIN(ctx, __func__, "schemalen = %zu", strlen(schema));

	if( ctx->adl == NULL )
	{
		if( (ctx->adl = malloc(sizeof(attr_dfn_list_t))) == NULL )
		{
			retval = LDAP_OPERATIONS_ERROR;
			goto out;
		}
		SLIST_INIT(LDE_LIST_HEAD(ctx->adl));
		ctx->adl->cnt = 0;
	}

	ad = ldap_str2attributetype(schema, &retval, &errpos,
			LDAP_SCHEMA_ALLOW_ALL);
	if( retval )
	{
		warnx("%s", ldap_scherr2str(retval));
		warnx("At %20s", errpos);
		retval = LDAP_OPERATIONS_ERROR;
	}
	else
	{
		int found = 0;

		new = attr_dfn_new(ad);
		SLIST_FOREACH(tmp, LDE_LIST_HEAD(ctx->adl), next)
		{
			if( strcasecmp(tmp->name, new->name) == 0 )
			{
				found = 1;
				break;
			}
		}
		if( ! found )
		{
			LOG(ctx, 2, "Adding Attribute Definition: %s", new->name);
			SLIST_INSERT_HEAD(LDE_LIST_HEAD(ctx->adl), new, next);
			ctx->adl->cnt++;
		}
	}

out:
	TRACEOUT(ctx, __func__, "Returning 0x%02x", retval);

	return(retval);
}

char *
lde_get_attr_descr(runtime_t *ctx, const char *name, ber_len_t *sz)
{
	attr_dfn_entry_t *cur;

	assert(ctx != NULL);
	assert(ctx->adl != NULL);
	assert(name != NULL);
	TRACEIN(ctx, __func__, "Looking for description of %s", name);

	SLIST_FOREACH(cur, LDE_LIST_HEAD(ctx->adl), next)
	{
		if( strcasecmp(cur->name, name) == 0 )
		{
			*sz = (ber_len_t)strlen(cur->desc);
			return (cur->desc);
		}
	}

	return (NULL);
}

static attr_dfn_entry_t *
attr_dfn_new(LDAPAttributeType *lat)
{
	attr_dfn_entry_t *retval;

	if( (retval = malloc(sizeof(attr_dfn_entry_t))) == NULL )
		return NULL;
	if( lat == NULL || lat->at_names == NULL || lat->at_names[0] == NULL )
		return NULL;

	memset(retval, 0, sizeof(attr_dfn_entry_t));
	retval->name = strdup(lat->at_names[0]);
	if( lat->at_desc == NULL )
		retval->desc = strdup("No description available");
	else
		retval->desc = strdup(lat->at_desc);
	assert(retval->name != NULL);
	assert(retval->desc != NULL);

	return (retval);
}
